"""
数据血缘相关API
"""

from typing import Dict, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session

from app.core.database import get_db
from app.core.neo4j_client import neo4j_client
from app.services.lineage_sync_service import lineage_sync_service
from app.models.lineage import ParseTask, LineageNodeCache, LineageEdgeCache
from app.core.logger import logger

router = APIRouter(prefix="/lineage", tags=["数据血缘"])


@router.get("/graph", summary="获取血缘图数据")
async def get_lineage_graph(
    table_id: Optional[str] = Query(None, description="表ID，为空时返回全部"),
    depth: int = Query(3, ge=1, le=10, description="血缘深度"),
    limit: int = Query(100, ge=1, le=1000, description="返回节点数量限制"),
    use_cache: bool = Query(True, description="是否使用缓存"),
    db: Session = Depends(get_db)
):
    """
    获取数据血缘图
    
    - **table_id**: 表ID，指定时返回该表的血缘关系
    - **depth**: 血缘查询深度
    - **limit**: 返回的节点数量限制
    - **use_cache**: 是否优先使用缓存数据
    """
    try:
        if use_cache:
            # 优先从缓存获取
            result = await _get_lineage_from_cache(table_id, limit, db)
            if result['nodes'] or result['edges']:
                return {
                    "success": True,
                    "data": result,
                    "source": "cache"
                }
        
        # 从Neo4j获取
        if not neo4j_client.is_connected():
            raise HTTPException(status_code=503, detail="Neo4j服务不可用")
        
        if table_id:
            result = neo4j_client.get_table_lineage_graph(table_id, limit)
        else:
            result = neo4j_client.get_table_lineage_graph(None, limit)
        
        return {
            "success": True,
            "data": result,
            "source": "neo4j"
        }
        
    except Exception as e:
        logger.error(f"获取血缘图失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取血缘图失败: {str(e)}")


@router.get("/upstream/{table_id}", summary="获取上游血缘")
async def get_upstream_lineage(
    table_id: str,
    depth: int = Query(3, ge=1, le=10, description="查询深度"),
    db: Session = Depends(get_db)
):
    """获取指定表的上游血缘关系"""
    try:
        if not neo4j_client.is_connected():
            raise HTTPException(status_code=503, detail="Neo4j服务不可用")
        
        result = neo4j_client.get_lineage_upstream(table_id, depth)
        
        return {
            "success": True,
            "data": result,
            "table_id": table_id,
            "direction": "upstream",
            "depth": depth
        }
        
    except Exception as e:
        logger.error(f"获取上游血缘失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取上游血缘失败: {str(e)}")


@router.get("/downstream/{table_id}", summary="获取下游血缘")
async def get_downstream_lineage(
    table_id: str,
    depth: int = Query(3, ge=1, le=10, description="查询深度"),
    db: Session = Depends(get_db)
):
    """获取指定表的下游血缘关系"""
    try:
        if not neo4j_client.is_connected():
            raise HTTPException(status_code=503, detail="Neo4j服务不可用")
        
        result = neo4j_client.get_lineage_downstream(table_id, depth)
        
        return {
            "success": True,
            "data": result,
            "table_id": table_id,
            "direction": "downstream",
            "depth": depth
        }
        
    except Exception as e:
        logger.error(f"获取下游血缘失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取下游血缘失败: {str(e)}")


@router.get("/columns/{table_id}", summary="获取字段级血缘")
async def get_column_lineage(
    table_id: str,
    limit: int = Query(100, ge=1, le=500, description="返回数量限制"),
    db: Session = Depends(get_db)
):
    """获取指定表的字段级血缘关系"""
    try:
        if not neo4j_client.is_connected():
            raise HTTPException(status_code=503, detail="Neo4j服务不可用")
        
        result = neo4j_client.get_column_lineage_graph(table_id, limit)
        
        return {
            "success": True,
            "data": result,
            "table_id": table_id,
            "type": "column_lineage"
        }
        
    except Exception as e:
        logger.error(f"获取字段血缘失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取字段血缘失败: {str(e)}")


@router.get("/search", summary="搜索血缘节点")
async def search_lineage_nodes(
    keyword: str = Query(..., min_length=1, description="搜索关键词"),
    node_type: Optional[str] = Query(None, description="节点类型过滤"),
    limit: int = Query(50, ge=1, le=200, description="返回数量限制"),
    db: Session = Depends(get_db)
):
    """搜索血缘图中的节点"""
    try:
        if not neo4j_client.is_connected():
            raise HTTPException(status_code=503, detail="Neo4j服务不可用")
        
        result = neo4j_client.search_nodes(keyword, node_type, limit)
        
        return {
            "success": True,
            "data": result,
            "keyword": keyword,
            "node_type": node_type,
            "count": len(result)
        }
        
    except Exception as e:
        logger.error(f"搜索节点失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"搜索节点失败: {str(e)}")


@router.get("/statistics", summary="获取血缘统计信息")
async def get_lineage_statistics(db: Session = Depends(get_db)):
    """获取血缘图的统计信息"""
    try:
        # 从Neo4j获取统计信息
        neo4j_stats = {}
        if neo4j_client.is_connected():
            neo4j_stats = neo4j_client.get_statistics()
        
        # 从MySQL获取统计信息
        mysql_stats = {
            "parse_tasks": db.query(ParseTask).count(),
            "cached_nodes": db.query(LineageNodeCache).count(),
            "cached_edges": db.query(LineageEdgeCache).count()
        }
        
        return {
            "success": True,
            "data": {
                "neo4j": neo4j_stats,
                "mysql": mysql_stats,
                "neo4j_connected": neo4j_client.is_connected()
            }
        }
        
    except Exception as e:
        logger.error(f"获取统计信息失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取统计信息失败: {str(e)}")


@router.post("/sync/{task_id}", summary="同步任务血缘")
async def sync_task_lineage(
    task_id: int,
    force_full: bool = Query(False, description="是否强制全量同步"),
    db: Session = Depends(get_db)
):
    """同步指定任务的血缘数据到Neo4j"""
    try:
        result = lineage_sync_service.sync_task_lineage(task_id, db, force_full)
        
        if result['success']:
            return {
                "success": True,
                "message": result['message'],
                "data": result
            }
        else:
            raise HTTPException(status_code=400, detail=result['message'])
            
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"同步血缘失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"同步血缘失败: {str(e)}")


@router.post("/sync/incremental", summary="增量同步血缘")
async def incremental_sync_lineage(db: Session = Depends(get_db)):
    """从Dinky增量同步血缘数据"""
    try:
        result = lineage_sync_service.incremental_sync_from_dinky(db)
        
        if result['success']:
            return {
                "success": True,
                "message": result['message'],
                "data": result
            }
        else:
            raise HTTPException(status_code=400, detail=result['message'])
            
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"增量同步失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"增量同步失败: {str(e)}")


async def _get_lineage_from_cache(table_id: Optional[str], limit: int, db: Session) -> Dict:
    """从缓存获取血缘数据"""
    try:
        # 获取节点缓存
        nodes_query = db.query(LineageNodeCache).filter(LineageNodeCache.is_active == True)
        if table_id:
            # 如果指定了表ID，获取相关节点
            nodes_query = nodes_query.filter(
                LineageNodeCache.node_id.like(f"%{table_id}%")
            )
        
        nodes = nodes_query.limit(limit).all()
        
        # 获取边缓存
        edges_query = db.query(LineageEdgeCache).filter(LineageEdgeCache.is_active == True)
        if table_id:
            # 获取相关边
            edges_query = edges_query.filter(
                (LineageEdgeCache.source_node_id.like(f"%{table_id}%")) |
                (LineageEdgeCache.target_node_id.like(f"%{table_id}%"))
            )
        
        edges = edges_query.limit(limit).all()
        
        # 转换为API格式
        nodes_data = []
        for node in nodes:
            nodes_data.append({
                "id": node.node_id,
                "type": node.node_type.value,
                "name": node.node_name,
                "database": node.database_name,
                "schema": node.schema_name,
                "table": node.table_name,
                "column": node.column_name,
                "properties": node.node_properties or {},
                "updated_at": node.updated_at.isoformat() if node.updated_at else None
            })
        
        edges_data = []
        for edge in edges:
            edges_data.append({
                "id": edge.edge_id,
                "source": edge.source_node_id,
                "target": edge.target_node_id,
                "type": edge.relationship_type.value,
                "sql_fragment": edge.sql_fragment,
                "transformation": edge.transformation_logic,
                "properties": edge.edge_properties or {},
                "updated_at": edge.updated_at.isoformat() if edge.updated_at else None
            })
        
        return {
            "nodes": nodes_data,
            "edges": edges_data,
            "stats": {
                "node_count": len(nodes_data),
                "edge_count": len(edges_data)
            }
        }
        
    except Exception as e:
        logger.error(f"从缓存获取血缘数据失败: {str(e)}")
        return {"nodes": [], "edges": [], "stats": {"node_count": 0, "edge_count": 0}}
